package com.example.imagecompressor.controller;

import com.example.imagecompressor.dto.ProcessingResult;
import com.example.imagecompressor.model.OutputFormat;
import com.example.imagecompressor.service.AsyncImageProcessingWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

@RestController
@RequestMapping("/api/images")
public class ImageUploadController {

    private static final Logger logger = LoggerFactory.getLogger(ImageUploadController.class);

    private final AsyncImageProcessingWrapper asyncImageProcessingWrapper;
    private final Path outputDirectory = Paths.get("output-images");

    @Autowired
    public ImageUploadController(AsyncImageProcessingWrapper asyncImageProcessingWrapper) {
        this.asyncImageProcessingWrapper = asyncImageProcessingWrapper;
        if (!Files.exists(outputDirectory) || !Files.isDirectory(outputDirectory)) {
            logger.warn("Output directory may not exist yet or is not a directory: {}", outputDirectory.toAbsolutePath());
        }
    }

    @PostMapping("/upload")
    public ResponseEntity<?> handleFileUpload(
            @RequestParam("files") MultipartFile[] files,
            @RequestParam("outputFormat") String outputFormatStr) {

        if (files == null || files.length == 0) {
            return ResponseEntity.badRequest().body("请至少选择一个文件上传。");
        }

        OutputFormat outputFormat;
        try {
            outputFormat = OutputFormat.valueOf(outputFormatStr.toUpperCase());
        } catch (IllegalArgumentException e) {
            logger.warn("Received invalid output format: {}", outputFormatStr);
            return ResponseEntity.badRequest().body("无效的输出格式: " + outputFormatStr);
        }

        logger.info("接收到 {} 个文件进行压缩，输出格式: {}", files.length, outputFormat);
        List<String> receivedFileNames = Arrays.stream(files)
                .map(MultipartFile::getOriginalFilename)
                .collect(Collectors.toList());
        logger.debug("文件名: {}", receivedFileNames);

        List<CompletableFuture<ProcessingResult>> futures = Arrays.stream(files)
                .map(file -> asyncImageProcessingWrapper.processFileAsync(file, outputFormat))
                .collect(Collectors.toList());

        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));

        try {
            allFutures.join();
            logger.info("All compression tasks completed for this request.");
        } catch (Exception e) {
            logger.error("Error waiting for compression tasks to complete", e);
        }

        List<ProcessingResult> results = futures.stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList());

        return ResponseEntity.ok(results);
    }

    @GetMapping("/download/{filename:.+}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String filename, HttpServletRequest request) {
        logger.info("Download request received for file: {}", filename);

        try {
            Path filePath = outputDirectory.resolve(filename).normalize();

            if (!filePath.startsWith(outputDirectory.normalize())) {
                 logger.warn("Attempted path traversal: {}", filename);
                 return ResponseEntity.badRequest().build();
            }

            Resource resource = new UrlResource(filePath.toUri());

            if (resource.exists() && resource.isReadable()) {
                String contentType = null;
                try {
                    contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
                } catch (IOException ex) {
                    logger.info("Could not determine file type for {}, using default.", filename);
                }
                if (contentType == null) {
                    contentType = "application/octet-stream";
                }

                logger.info("Serving file {} with content type {}", filename, contentType);

                ContentDisposition contentDisposition = ContentDisposition.attachment()
                        .filename(filename, StandardCharsets.UTF_8)
                        .build();

                return ResponseEntity.ok()
                        .contentType(MediaType.parseMediaType(contentType))
                        .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString())
                        .body(resource);
            } else {
                logger.warn("Requested file not found or not readable: {}", filePath);
                return ResponseEntity.notFound().build();
            }
        } catch (MalformedURLException e) {
            logger.error("Error creating URL for file path: {}", filename, e);
            return ResponseEntity.internalServerError().build();
        } catch (Exception e) {
             logger.error("Error during file download for {}: {}", filename, e.getMessage(), e);
             return ResponseEntity.internalServerError().build();
        }
    }
} 